Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

benchmarks: Implement benchmarks for streamable #10388

Merged
merged 12 commits into from
Feb 24, 2022

Conversation

xdustinface
Copy link
Contributor

@xdustinface xdustinface commented Feb 23, 2022

Implements some benchmarks for streamable object creation, byte conversions and json conversions for the classes FullBlock and BenchmarkClass. The BenchmarkClass can probably still be improved so im open for suggestions :) The benchmark collects iterations over a specific time window and this can be done multiple runs to get an average result. See the parameter below:

Usage

python benchmarks/streamable.py --help
Usage: streamable.py [OPTIONS]

Options:
  -d, --data [all|benchmark|full_block]
  -m, --mode [all|creation|to_bytes|from_bytes|to_json|from_json]
  -r, --runs INTEGER              Number of benchmark runs to average results
  -t, --ms INTEGER                Milliseconds per run
  --live / --no-live              Print live results (slower)
  --help                          Show this message and exit.

Example run

Run all benchmarks with the class: BenchmarkClass
Run all benchmarks with the class: BenchmarkClass
runs       | ms/run     | ns/iteration | mode       | avg iterations | stdev iterations
100        | 47         | 18           | creation   |           2536 |         22.81
100        | 50         | 462          | to_bytes   |            108 |          0.69
100        | 49         | 275          | from_bytes |            181 |          3.92
100        | 50         | 927          | to_json    |             54 |          1.38
100        | 50         | 1089         | from_json  |             46 |          0.89

Run all benchmarks with the class: FullBlock
runs       | ms/run     | ns/iteration | mode       | avg iterations | stdev iterations
100        | 48         | 23           | creation   |           2077 |         63.08
100        | 49         | 114          | to_bytes   |            434 |         10.39
100        | 51         | 2923         | from_bytes |             17 |          0.42
100        | 50         | 422          | to_json    |            118 |          2.01
100        | 51         | 2974         | from_json  |             17 |          0.45

Benchmark classes

@dataclass(frozen=True)
@streamable
class BenchmarkInner(Streamable):
    a: str


@dataclass(frozen=True)
@streamable
class BenchmarkMiddle(Streamable):
    a: uint64
    b: List[bytes32]
    c: Tuple[str, bool, uint8, List[bytes]]
    d: Tuple[BenchmarkInner, BenchmarkInner]
    e: BenchmarkInner


@dataclass(frozen=True)
@streamable
class BenchmarkClass(Streamable):
    a: Optional[BenchmarkMiddle]
    b: Optional[BenchmarkMiddle]
    c: BenchmarkMiddle
    d: List[BenchmarkMiddle]
    e: Tuple[BenchmarkMiddle, BenchmarkMiddle, BenchmarkMiddle]

@mariano54
Copy link
Contributor

Very cool. I suggest naming the file bench_streamable so when we search for filenames we don't get duplicates with ide. Also it would be nice to have the avg ms time for each iteration

@xdustinface
Copy link
Contributor Author

Very cool. I suggest naming the file bench_streamable so when we search for filenames we don't get duplicates with ide.

I don't care that much and i can rename if you really want it but isn't that what folders and packages are about? We also have util.py in several places and i mean, even with the bench prefix it gets listed as you can see with the test_streamable :)

image

Also it would be nice to have the avg ms time for each iteration

Not sure if i understand what you mean exactly. What it currently prints as result is "sum of runs per data and mode" / runs.

average_duration: int = int(sum(results[current_data][current_mode]) / runs)
Can you explain what you would like to see?

@mariano54
Copy link
Contributor

It's personal preference, I like to be able to just press 4-5 keys on the keyboard and navigate to a file deterministically without having to check which folder it's in, etc. No big deal though

@mariano54
Copy link
Contributor

The result is always 1 second. That seems wrong, it should be the time taken for 1 iteration right?

@xdustinface
Copy link
Contributor Author

The result is always 1 second. That seems wrong

That was by purpose actually. I trimmed the number of iterations per test separetly so that they all have about the same runtime.

See 06356bc for another approach which is to "collect the iterations for a given time" instead of "measuring the time for a given number of iterations". What do you think? I adjusted the initial desctiption but still here is an example run:

Run all benchmarks with the class: BenchmarkClass
runs       | ms/run     | mode       | avg iterations
50         | 50         | creation   |          2618
50         | 50         | to_bytes   |           110
50         | 50         | from_bytes |           175
50         | 50         | to_json    |            53
50         | 50         | from_json  |            45

Run all benchmarks with the class: FullBlock
runs       | ms/run     | mode       | avg iterations
50         | 50         | creation   |          2140
50         | 50         | to_bytes   |           449
50         | 50         | from_bytes |            18
50         | 50         | to_json    |           111
50         | 50         | from_json  |            16

@xdustinface
Copy link
Contributor Author

Added std deviation field, see:

Run all benchmarks with the class: BenchmarkClass
runs       | ms/run     | mode       | avg iterations | std deviation
50         | 50         | creation   |           2593 |         27.46
50         | 50         | to_bytes   |            110 |          1.02
50         | 50         | from_bytes |            175 |          4.11
50         | 50         | to_json    |             53 |          1.38
50         | 50         | from_json  |             45 |           0.6

Run all benchmarks with the class: FullBlock
runs       | ms/run     | mode       | avg iterations | std deviation
50         | 50         | creation   |           2126 |         25.88
50         | 50         | to_bytes   |            439 |          9.65
50         | 50         | from_bytes |             17 |          0.63
50         | 50         | to_json    |            115 |          1.59
50         | 50         | from_json  |             16 |          0.49

@mariano54
Copy link
Contributor

I'ts nice because it means you don't have to wait a long time for the slow operations. I prefer to additionally look at the ms (or nanoseconds) taken per run as a way to visualize the speed of something, as opposed to trying to increase the number of iterations.

benchmarks/streamable.py Outdated Show resolved Hide resolved
benchmarks/streamable.py Outdated Show resolved Hide resolved
benchmarks/streamable.py Outdated Show resolved Hide resolved
@xdustinface
Copy link
Contributor Author

@mariano54 Added ns/iteration, example run:

Run all benchmarks with the class: BenchmarkClass
runs       | ms/run     | ns/iteration | mode       | avg iterations | stdev iterations
100        | 47         | 18           | creation   |           2536 |         22.81
100        | 50         | 462          | to_bytes   |            108 |          0.69
100        | 49         | 275          | from_bytes |            181 |          3.92
100        | 50         | 927          | to_json    |             54 |          1.38
100        | 50         | 1089         | from_json  |             46 |          0.89

Run all benchmarks with the class: FullBlock
runs       | ms/run     | ns/iteration | mode       | avg iterations | stdev iterations
100        | 48         | 23           | creation   |           2077 |         63.08
100        | 49         | 114          | to_bytes   |            434 |         10.39
100        | 51         | 2923         | from_bytes |             17 |          0.42
100        | 50         | 422          | to_json    |            118 |          2.01
100        | 51         | 2974         | from_json  |             17 |          0.45

@xdustinface
Copy link
Contributor Author

Okay improved the logging a bit. I think thats it from me now, any other requests? Example:

runs: 100, ms/run: 50, benchmarks: all, data: BenchmarkClass
mode       | µs/iteration | avg iterations | stdev iterations %
creation   | 19           |           2518 |                0.4
to_bytes   | 476          |            105 |               1.43
from_bytes | 290          |            172 |               0.75
to_json    | 967          |             52 |               1.92
from_json  | 1130         |             44 |               0.93

runs: 100, ms/run: 50, benchmarks: all, data: FullBlock
mode       | µs/iteration | avg iterations | stdev iterations %
creation   | 23           |           2056 |               1.18
to_bytes   | 114          |            433 |                0.9
from_bytes | 2846         |             17 |               0.58
to_json    | 435          |            115 |               1.06
from_json  | 3165         |             16 |               2.56

@xdustinface
Copy link
Contributor Author

I think thats it from me now

wasn't, but now.. :

runs: 100, ms/run: 50, benchmarks: all, data: BenchmarkClass
mode       | µs/iteration | stdev µs/iteration % | avg iterations/run | stdev iterations/run %
creation   | 18.24        |                 6.85 |               2465 |                   0.58
to_bytes   | 455.4        |                 1.66 |                109 |                   1.06
from_bytes | 275.55       |                 2.01 |                180 |                    1.0
to_json    | 946.72       |                 3.76 |                 53 |                   2.25
from_json  | 1086.42      |                 2.47 |                 46 |                   1.54

runs: 100, ms/run: 50, benchmarks: all, data: FullBlock
mode       | µs/iteration | stdev µs/iteration % | avg iterations/run | stdev iterations/run %
creation   | 22.83        |                 6.78 |               2016 |                   0.97
to_bytes   | 112.65       |                 4.93 |                437 |                   1.15
from_bytes | 2775.47      |                 2.04 |                 18 |                   2.63
to_json    | 424.53       |                 4.76 |                117 |                   1.11
from_json  | 3140.45      |                 4.96 |                 16 |                   3.19

@mariano54
Copy link
Contributor

mariano54 commented Feb 24, 2022

Looks really good now.

@wjblanke wjblanke merged commit cdf48f7 into Chia-Network:main Feb 24, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants